package com.company.project.core.common;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

public class HttpClientUtils {

    private static final Logger log = LoggerFactory.getLogger(HttpClientUtils.class);

    private static PoolingHttpClientConnectionManager cm = null;
    private static HttpClient httpClient = null;

    static {
        cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);
        cm.setDefaultMaxPerRoute(100);
        cm.setValidateAfterInactivity(60 * 1000);
    }

    public static CloseableHttpClient getHttpClient() {
        RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
        CloseableHttpClient client = HttpClients.custom().setConnectionManager(cm).setDefaultRequestConfig(globalConfig).build();
        return client;
    }

    /**
     * post方式请求服务器
     *
     * @param url     请求地址
     * @param content 请求内容
     * @return AipResponse
     */
    public static String post(String url, String content, int socketTimeout) {
        String responseStr = "";
        HttpPost post = null;

        try {
            if (httpClient == null) {
                synchronized (cm) {
                    if (httpClient == null) {
                        httpClient = getHttpClient();
                    }
                }
            }
            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(60000).build();
            post = new HttpPost(url);
            // 构造消息头
            post.setHeader("Content-type", "application/json; charset=utf-8");
            post.setHeader("Connection", "Close");
            post.setConfig(requestConfig);

            //构建消息实体
            StringEntity entity = new StringEntity(content, StandardCharsets.UTF_8);
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            post.setEntity(entity);

            HttpResponse response = httpClient.execute(post);

            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                throw new RuntimeException(String.format("翻译请求失败:%d", statusCode));
            } else {
                responseStr = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }
        } catch (ConnectTimeoutException | ConnectException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
        return responseStr;
    }

    public static String get(String url) throws Exception {
        if (httpClient == null) {
            synchronized (cm) {
                if (httpClient == null) {
                    httpClient = getHttpClient();
                }
            }
        }

        String strResult = "";
        HttpGet httpGet = null;
        try {
            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
            httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);
            httpGet.addHeader("Content-Type", "application/x-www-form-urlencoded");
            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                strResult = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            } else {
                throw new Exception(String.format("翻译请求失败:%d %s", statusLine.getStatusCode(), response.getStatusLine().getReasonPhrase()));
            }
        } finally {
            if (httpGet != null) {
                httpGet.releaseConnection();
            }
        }
        return strResult;
    }

    public static String post(String url) throws Exception {
        if (httpClient == null) {
            synchronized (cm) {
                if (httpClient == null) {
                    httpClient = getHttpClient();
                }
            }
        }
        HttpPost httpPost = null;
        String strResult;
        try {
            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
            HttpResponse response = httpClient.execute(httpPost);
            StatusLine statusLine = response.getStatusLine();
            if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                strResult = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            } else {
                throw new Exception(String.format("翻译请求失败:%d %s", statusLine.getStatusCode(), response.getStatusLine().getReasonPhrase()));
            }

        } finally {
            if (httpPost != null) {
                httpPost.releaseConnection();
            }
        }
        return strResult;
    }


    public static String uploadYunyiDocFile(String url, String localFile, Map<String, String> params) throws Exception {
        HttpPost post = null;
        String resultString = "";
        try {
            if (httpClient == null) {
                synchronized (cm) {
                    if (httpClient == null) {
                        httpClient = getHttpClient();
                    }
                }
            }

            // 把文件转换成流对象FileBody
            FileBody bin = new FileBody(new File(localFile));

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();

            // 相当于<input type="file" name="file"/>
            builder.addPart("doc", bin);
            // 相当于<input type="text" name="userName" value=userName>
            if (params != null) {
                for (String key : params.keySet()) {
                    builder.addPart(key,
                            new StringBody(params.get(key), ContentType.create("text/plain", StandardCharsets.UTF_8)));
                }
            }

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
            post = new HttpPost(url);
            post.setConfig(requestConfig);

            HttpEntity reqEntity = builder.build();
            post.setEntity(reqEntity);


            // 发起请求 并返回请求的响应
            HttpResponse response = httpClient.execute(post, HttpClientContext.create());

            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                String reasonPhrase = response.getStatusLine().getReasonPhrase();
                throw new Exception(String.format("翻译请求失败:%d %s", statusCode, reasonPhrase));
            } else {
                resultString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }

        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
        return resultString;
    }

    public static String postForm(String url, String params) throws Exception {
        HttpPost post = null;
        String resultString = "";
        try {
            if (httpClient == null) {
                synchronized (cm) {
                    if (httpClient == null) {
                        httpClient = getHttpClient();
                    }
                }
            }

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
            post = new HttpPost(url);
            post.setConfig(requestConfig);
            post.addHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
            HttpEntity reqEntity = new StringEntity(params, StandardCharsets.UTF_8);
            post.setEntity(reqEntity);

            // 发起请求 并返回请求的响应
            HttpResponse response = httpClient.execute(post);

            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                String reasonPhrase = response.getStatusLine().getReasonPhrase();
                throw new Exception(String.format("翻译请求失败:%d %s", statusCode, reasonPhrase));
            } else {
                resultString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }

        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
        return resultString;
    }

    public static void uploadFileAndDownload(String url, String localFile, String outputFile) throws Exception {
        HttpPost post = null;
        try {
            if (httpClient == null) {
                synchronized (cm) {
                    if (httpClient == null) {
                        httpClient = getHttpClient();
                    }
                }
            }

            // 把文件转换成流对象FileBody
            FileBody bin = new FileBody(new File(localFile));

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();

            // 相当于<input type="file" name="file"/>
            builder.addPart("file", bin);
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
            post = new HttpPost(url);
            post.setConfig(requestConfig);

            HttpEntity reqEntity = builder.build();
            post.setEntity(reqEntity);


            // 发起请求 并返回请求的响应
            HttpResponse response = httpClient.execute(post, HttpClientContext.create());
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                throw new Exception(String.format("office 转换请求失败:%d", statusCode));
            } else {
                HttpEntity entity = response.getEntity();
                InputStream is = entity.getContent();
                File file = new File(outputFile);
                FileOutputStream fileout = new FileOutputStream(file);
                /**
                 * 根据实际运行效果 设置缓冲区大小
                 */
                byte[] buffer = new byte[4096];
                int ch;
                while ((ch = is.read(buffer)) != -1) {
                    fileout.write(buffer, 0, ch);
                }
                is.close();
                fileout.flush();
                fileout.close();
            }
        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
    }

    /**
     * post方式请求服务器
     *
     * @param url  请求地址
     * @param json 请求内容
     * @return AipResponse
     */
    public static String postJson(String url, String json) throws Exception {
        String responseStr = "";
        HttpPost post = null;
        try {
            if (httpClient == null) {
                synchronized (cm) {
                    if (httpClient == null) {
                        httpClient = getHttpClient();
                    }
                }
            }
            // 设置超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
            post = new HttpPost(url);
            // 构造消息头
            post.setHeader("Content-type", "application/json; charset=utf-8");
            post.setHeader("Connection", "Close");
            post.setConfig(requestConfig);

            //构建消息实体
            StringEntity entity = new StringEntity(json, StandardCharsets.UTF_8);
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            post.setEntity(entity);

            HttpResponse response = httpClient.execute(post);

            // 检验返回码
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                String reasonPhrase = response.getStatusLine().getReasonPhrase();
                throw new Exception(String.format("翻译请求失败:%d %s", statusCode, reasonPhrase));
            } else {
                responseStr = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            }
        } finally {
            if (post != null) {
                post.releaseConnection();
            }
        }
        return responseStr;
    }

    public static void main(String[] args) {
        try {
            String mturl = "http://192.168.20.79:8080/?src_str=";
            String result = HttpClientUtils.get(mturl + URLEncoder.encode(" Every day, Kendall tried hard to pick it up with her right hand.", "utf-8").replace("+", "%20"));
            System.out.println(result);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
